﻿using System;
using System.Net;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Collections.Generic;
#if SILVERLIGHT
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
#endif

namespace Microsoft.PlayerFramework
{
    /// <summary>
    /// Provides an IInteractiveViewModel implementation for MediaPlayer
    /// </summary>
    public class InteractiveViewModel : InteractiveViewModelBase
    {
        MediaPlayer MediaPlayer;

        /// <summary>
        /// Creates a new instance of InteractiveViewModel
        /// </summary>
        public InteractiveViewModel(MediaPlayer mediaPlayer)
        {
            MediaPlayer = mediaPlayer;

            MediaPlayer.IsPlayResumeEnabledChanged += (s, e) => NotifyIsPlayResumeEnabledChanged();
            MediaPlayer.IsPauseEnabledChanged += (s, e) => NotifyIsPauseEnabledChanged();
            MediaPlayer.IsStopEnabledChanged += (s, e) => NotifyIsStopEnabledChanged();
            MediaPlayer.IsReplayEnabledChanged += (s, e) => NotifyIsReplayEnabledChanged();
            MediaPlayer.IsAudioSelectionEnabledChanged += (s, e) => NotifyIsAudioSelectionEnabledChanged();
            MediaPlayer.IsCaptionsEnabledChanged += (s, e) => NotifyIsCaptionsEnabledChanged();
            MediaPlayer.IsRewindEnabledChanged += (s, e) => NotifyIsRewindEnabledChanged();
            MediaPlayer.IsFastForwardEnabledChanged += (s, e) => NotifyIsFastForwardEnabledChanged();
            MediaPlayer.IsSlowMotionEnabledChanged += (s, e) => NotifyIsSlowMotionEnabledChanged();
            MediaPlayer.IsSeekEnabledChanged += (s, e) => NotifyIsSeekEnabledChanged();
            MediaPlayer.IsSkipPreviousEnabledChanged += (s, e) => NotifyIsSkipPreviousEnabledChanged();
            MediaPlayer.IsSkipNextEnabledChanged += (s, e) => NotifyIsSkipNextEnabledChanged();
            MediaPlayer.IsSkipBackEnabledChanged += (s, e) => NotifyIsSkipBackEnabledChanged();
            MediaPlayer.IsSkipAheadEnabledChanged += (s, e) => NotifyIsSkipAheadEnabledChanged();
            MediaPlayer.IsScrubbingEnabledChanged += (s, e) => NotifyIsScrubbingEnabledChanged();
            MediaPlayer.IsGoLiveEnabledChanged += (s, e) => NotifyIsGoLiveEnabledChanged();

            MediaPlayer.IsPlayResumeAllowedChanged += (s, e) => NotifyIsPlayResumeEnabledChanged();
            MediaPlayer.IsPauseAllowedChanged += (s, e) => NotifyIsPauseEnabledChanged();
            MediaPlayer.IsStopAllowedChanged += (s, e) => NotifyIsStopEnabledChanged();
            MediaPlayer.IsReplayAllowedChanged += (s, e) => NotifyIsReplayEnabledChanged();
            MediaPlayer.IsAudioSelectionAllowedChanged += (s, e) => NotifyIsAudioSelectionEnabledChanged();
            MediaPlayer.IsCaptionsAllowedChanged += (s, e) => NotifyIsCaptionsEnabledChanged();
            MediaPlayer.IsRewindAllowedChanged += (s, e) => NotifyIsRewindEnabledChanged();
            MediaPlayer.IsFastForwardAllowedChanged += (s, e) => NotifyIsFastForwardEnabledChanged();
            MediaPlayer.IsSlowMotionAllowedChanged += (s, e) => NotifyIsSlowMotionEnabledChanged();
            MediaPlayer.IsSeekAllowedChanged += (s, e) => NotifyIsSeekEnabledChanged();
            MediaPlayer.IsSkipPreviousAllowedChanged += (s, e) => NotifyIsSkipPreviousEnabledChanged();
            MediaPlayer.IsSkipNextAllowedChanged += (s, e) => NotifyIsSkipNextEnabledChanged();
            MediaPlayer.IsSkipBackAllowedChanged += (s, e) => NotifyIsSkipBackEnabledChanged();
            MediaPlayer.IsSkipAheadAllowedChanged += (s, e) => NotifyIsSkipAheadEnabledChanged();
            MediaPlayer.IsScrubbingAllowedChanged += (s, e) => NotifyIsScrubbingEnabledChanged();
            MediaPlayer.IsGoLiveAllowedChanged += (s, e) => NotifyIsGoLiveEnabledChanged();

            MediaPlayer.IsMutedChanged += (s, e) => OnPropertyChanged(() => IsMuted);
            MediaPlayer.IsFullScreenChanged += (s, e) => OnPropertyChanged(() => IsFullScreen);
            MediaPlayer.IsCaptionsActiveChanged += (s, e) => OnPropertyChanged(() => IsCaptionsActive);
            MediaPlayer.IsSlowMotionChanged += (s, e) => OnPropertyChanged(() => IsSlowMotion);
            MediaPlayer.CurrentStateChanged += (s, e) => OnCurrentStateChanged(e);
            MediaPlayer.BufferingProgressChanged += (s, e) => OnPropertyChanged(() => BufferingProgress);
            MediaPlayer.DownloadProgressChanged += (s, e) => OnPropertyChanged(() => DownloadProgress);
            MediaPlayer.VolumeChanged += (s, e) => OnPropertyChanged(() => Volume);
            MediaPlayer.StartTimeChanged += (s, e) => OnPropertyChanged(() => StartTime);
            MediaPlayer.EndTimeChanged += (s, e) => OnPropertyChanged(() => EndTime);
            MediaPlayer.DurationChanged += (s, e) => OnPropertyChanged(() => Duration);
            MediaPlayer.TimeRemainingChanged += (s, e) => OnPropertyChanged(() => TimeRemaining);
            MediaPlayer.LivePositionChanged += (s, e) => OnPropertyChanged(() => MaxPosition );
            MediaPlayer.TimeFormatConverterChanged += (s, e) => OnPropertyChanged(() => TimeFormatConverter );
            MediaPlayer.SkipBackIntervalChanged += (s, e) => OnPropertyChanged(() => SkipBackInterval);
            MediaPlayer.SkipAheadIntervalChanged += (s, e) => OnPropertyChanged(() => SkipAheadInterval);
            MediaPlayer.PositionChanged += (s, e) => OnPropertyChanged(() => Position);
            MediaPlayer.SignalStrengthChanged += (s, e) => OnPropertyChanged(() => SignalStrength);
            MediaPlayer.MediaQualityChanged += (s, e) => OnPropertyChanged(() => MediaQuality);
            
            MediaPlayer.IsAudioSelectionVisibleChanged += (s, e) => OnPropertyChanged(() => IsAudioSelectionVisible);
            MediaPlayer.IsCaptionsVisibleChanged += (s, e) => OnPropertyChanged(() => IsCaptionsVisible);
            MediaPlayer.IsDurationVisibleChanged += (s, e) => OnPropertyChanged(() => IsDurationVisible);
            MediaPlayer.IsTimeRemainingVisibleChanged += (s, e) => OnPropertyChanged(() => IsTimeRemainingVisible);
            MediaPlayer.IsFastForwardVisibleChanged += (s, e) => OnPropertyChanged(() => IsFastForwardVisible);
            MediaPlayer.IsFullScreenVisibleChanged += (s, e) => OnPropertyChanged(() => IsFullScreenVisible);
            MediaPlayer.IsGoLiveVisibleChanged += (s, e) => OnPropertyChanged(() => IsGoLiveVisible);
            MediaPlayer.IsPlayPauseVisibleChanged += (s, e) => OnPropertyChanged(() => IsPlayPauseVisible);
            MediaPlayer.IsPositionVisibleChanged += (s, e) => OnPropertyChanged(() => IsPositionVisible);
            MediaPlayer.IsReplayVisibleChanged += (s, e) => OnPropertyChanged(() => IsReplayVisible);
            MediaPlayer.IsRewindVisibleChanged += (s, e) => OnPropertyChanged(() => IsRewindVisible);
            MediaPlayer.IsSkipPreviousVisibleChanged += (s, e) => OnPropertyChanged(() => IsSkipPreviousVisible);
            MediaPlayer.IsSkipNextVisibleChanged += (s, e) => OnPropertyChanged(() => IsSkipNextVisible);
            MediaPlayer.IsSkipBackVisibleChanged += (s, e) => OnPropertyChanged(() => IsSkipBackVisible);
            MediaPlayer.IsSkipAheadVisibleChanged += (s, e) => OnPropertyChanged(() => IsSkipAheadVisible);
            MediaPlayer.IsSlowMotionVisibleChanged += (s, e) => OnPropertyChanged(() => IsSlowMotionVisible);
            MediaPlayer.IsStopVisibleChanged += (s, e) => OnPropertyChanged(() => IsStopVisible);
            MediaPlayer.IsTimelineVisibleChanged += (s, e) => OnPropertyChanged(() => IsTimelineVisible);
            MediaPlayer.IsVolumeVisibleChanged += (s, e) => OnPropertyChanged(() => IsVolumeVisible);
            MediaPlayer.IsSignalStrengthVisibleChanged += (s, e) => OnPropertyChanged(() => IsSignalStrengthVisible);
            MediaPlayer.IsResolutionIndicatorVisibleChanged += (s, e) => OnPropertyChanged(() => IsResolutionIndicatorVisible);
#if SILVERLIGHT
            MediaPlayer.IsDisplayModeVisibleChanged += (s, e) => OnPropertyChanged(() => IsDisplayModeVisible);
#endif
        }

        #region Methods

        /// <inheritdoc /> 
        protected override void OnStop()
        {
            MediaPlayer.Stop();
        }

        /// <inheritdoc /> 
        protected override void OnPause()
        {
            MediaPlayer.Pause();
        }

        /// <inheritdoc /> 
        protected override void OnSetVolume(double volume)
        {
            MediaPlayer.Volume = volume;
        }

        /// <inheritdoc /> 
        protected override void OnSetSlowMotion(bool slowMotion)
        {
            MediaPlayer.IsSlowMotion = slowMotion;
        }

        /// <inheritdoc /> 
        protected override void OnSetMuted(bool muted)
        {
            MediaPlayer.IsMuted = muted;
        }

        /// <inheritdoc /> 
        protected override void OnSetFullScreen(bool fullScreen)
        {
            MediaPlayer.IsFullScreen = fullScreen;
        }

        /// <inheritdoc /> 
        protected override void OnInvokeCaptions()
        {
            MediaPlayer.InvokeCaptions();
        }

        /// <inheritdoc /> 
        protected override void OnInvokeAudioSelection()
        {
            MediaPlayer.InvokeAudioSelection();
        }

        /// <inheritdoc /> 
        protected override void OnSkipPrevious(VisualMarker marker)
        {
            MediaPlayer.Seek(marker != null ? GetMediaPlayerPosition(marker.Time) : MediaPlayer.StartTime);
        }

        /// <inheritdoc /> 
        protected override void OnSkipNext(VisualMarker marker)
        {
            MediaPlayer.Seek(marker != null ? GetMediaPlayerPosition(marker.Time) : MediaPlayer.LivePosition.GetValueOrDefault(MediaPlayer.Duration));
        }

        /// <inheritdoc /> 
        protected override void OnSkipBack(TimeSpan position)
        {
            MediaPlayer.Seek(GetMediaPlayerPosition(position));
        }

        /// <inheritdoc /> 
        protected override void OnSkipAhead(TimeSpan position)
        {
            MediaPlayer.Seek(GetMediaPlayerPosition(position));
        }

        /// <inheritdoc /> 
        protected override void OnSeek(TimeSpan position)
        {
            MediaPlayer.Seek(GetMediaPlayerPosition(position));
        }

        /// <inheritdoc /> 
        protected override void OnCompleteScrub(TimeSpan position, ref bool canceled)
        {
            MediaPlayer.CompleteScrub(GetMediaPlayerPosition(position), ref canceled);
        }

        /// <inheritdoc /> 
        protected override void OnStartScrub(TimeSpan position, out bool canceled)
        {
            MediaPlayer.StartScrub(GetMediaPlayerPosition(position), out canceled);
        }

        /// <inheritdoc /> 
        protected override void OnScrub(TimeSpan position, out bool canceled)
        {
            MediaPlayer.Scrub(GetMediaPlayerPosition(position), out canceled);
        }

        /// <inheritdoc /> 
        protected override void OnGoLive()
        {
            MediaPlayer.SeekToLive();
        }

        /// <inheritdoc /> 
        protected override void OnPlayResume()
        {
            MediaPlayer.PlayResume();
        }

        /// <inheritdoc /> 
        protected override void OnReplay()
        {
            MediaPlayer.Replay();
        }

        /// <inheritdoc /> 
        protected override void OnDecreasePlaybackRate()
        {
            MediaPlayer.DecreasePlaybackRate();
        }

        /// <inheritdoc /> 
        protected override void OnIncreasePlaybackRate()
        {
            MediaPlayer.IncreasePlaybackRate();
        }

        TimeSpan GetMediaPlayerPosition(TimeSpan viewModelPosition)
        {
            return MediaPlayer.IsStartTimeOffset ? viewModelPosition : MediaPlayer.StartTime.Add(viewModelPosition);
        }

        TimeSpan GetViewModelPosition(TimeSpan mediaPlayerPosition)
        {
            return MediaPlayer.IsStartTimeOffset ? mediaPlayerPosition : mediaPlayerPosition.Subtract(MediaPlayer.StartTime);
        }

        TimeSpan? GetViewModelPosition(TimeSpan? mediaPlayerPosition)
        {
            return mediaPlayerPosition.HasValue ? GetViewModelPosition(mediaPlayerPosition.Value) : mediaPlayerPosition;
        }

#if SILVERLIGHT
        /// <inheritdoc /> 
        protected override void OnCycleDisplayMode()
        {
            MediaPlayer.CycleDisplayMode();
        }
#endif
        #endregion

        #region AvailableCaptions
        /// <inheritdoc /> 
        public override IEnumerable<Caption> AvailableCaptions
        {
            get { return MediaPlayer.AvailableCaptions; }
        }
        #endregion

        #region SelectedCaption
        /// <inheritdoc /> 
        public override Caption SelectedCaption
        {
            get { return MediaPlayer.SelectedCaption; }
            set { MediaPlayer.SelectedCaption = value; }
        }
        #endregion

        #region AvailableAudioStreams
        /// <inheritdoc /> 
        public override IEnumerable<AudioStream> AvailableAudioStreams
        {
            get { return MediaPlayer.AvailableAudioStreams; }
        }
        #endregion

        #region SelectedAudioStream
        /// <inheritdoc /> 
        public override AudioStream SelectedAudioStream
        {
            get { return MediaPlayer.SelectedAudioStream; }
            set { MediaPlayer.SelectedAudioStream = value; }
        }
        #endregion

        #region VisualMarkers
        /// <inheritdoc /> 
        public override IEnumerable<VisualMarker> VisualMarkers
        {
            get { return MediaPlayer.VisualMarkers; }
        }
        #endregion
        
        #region IsGoLiveEnabled
        
        /// <inheritdoc /> 
        public override bool IsGoLiveEnabled
        {
            get { return MediaPlayer.IsGoLiveEnabled && MediaPlayer.IsGoLiveAllowed; }
        }
        #endregion

        #region IsPlayResumeEnabled

        /// <inheritdoc /> 
        public override bool IsPlayResumeEnabled
        {
            get { return MediaPlayer.IsPlayResumeEnabled && MediaPlayer.IsPlayResumeAllowed; }
        }
        #endregion

        #region IsPauseEnabled

        /// <inheritdoc /> 
        public override bool IsPauseEnabled
        {
            get { return MediaPlayer.IsPauseEnabled && MediaPlayer.IsPauseAllowed; }
        }

        #endregion

        #region IsStopEnabled

        /// <inheritdoc /> 
        public override bool IsStopEnabled
        {
            get { return MediaPlayer.IsStopEnabled && MediaPlayer.IsStopAllowed; }
        }

        #endregion

        #region IsReplayEnabled

        /// <inheritdoc /> 
        public override bool IsReplayEnabled
        {
            get { return MediaPlayer.IsReplayEnabled && MediaPlayer.IsReplayAllowed; }
        }

        #endregion

        #region IsAudioSelectionEnabled

        /// <inheritdoc /> 
        public override bool IsAudioSelectionEnabled
        {
            get { return MediaPlayer.IsAudioSelectionEnabled && MediaPlayer.IsAudioSelectionAllowed; }
        }

        #endregion

        #region IsCaptionsEnabled

        /// <inheritdoc /> 
        public override bool IsCaptionsEnabled
        {
            get { return MediaPlayer.IsCaptionsEnabled && MediaPlayer.IsCaptionsAllowed; }
        }

        #endregion

        #region IsRewindEnabled

        /// <inheritdoc /> 
        public override bool IsRewindEnabled
        {
            get { return MediaPlayer.IsRewindEnabled && MediaPlayer.IsRewindAllowed; }
        }

        #endregion

        #region IsFastForwardEnabled

        /// <inheritdoc /> 
        public override bool IsFastForwardEnabled
        {
            get { return MediaPlayer.IsFastForwardEnabled && MediaPlayer.IsFastForwardAllowed; }
        }

        #endregion

        #region IsSlowMotionEnabled

        /// <inheritdoc /> 
        public override bool IsSlowMotionEnabled
        {
            get { return MediaPlayer.IsSlowMotionEnabled && MediaPlayer.IsSlowMotionAllowed; }
        }

        #endregion

        #region IsSeekEnabled

        /// <inheritdoc /> 
        public override bool IsSeekEnabled
        {
            get { return MediaPlayer.IsSeekEnabled && MediaPlayer.IsSeekAllowed; }
        }

        #endregion

        #region IsSkipPreviousEnabled

        /// <inheritdoc /> 
        public override bool IsSkipPreviousEnabled
        {
            get { return MediaPlayer.IsSkipPreviousEnabled && MediaPlayer.IsSkipPreviousAllowed; }
        }

        #endregion

        #region IsSkipNextEnabled

        /// <inheritdoc /> 
        public override bool IsSkipNextEnabled
        {
            get
            {
                return MediaPlayer.IsSkipNextEnabled && MediaPlayer.IsSkipNextAllowed;
            }
        }

        #endregion

        #region IsSkipBackEnabled

        /// <inheritdoc /> 
        public override bool IsSkipBackEnabled
        {
            get { return MediaPlayer.IsSkipBackEnabled && MediaPlayer.IsSkipBackAllowed; }
        }

        #endregion

        #region IsSkipAheadEnabled

        /// <inheritdoc /> 
        public override bool IsSkipAheadEnabled
        {
            get
            {
                return MediaPlayer.IsSkipAheadEnabled && MediaPlayer.IsSkipAheadAllowed;
            }
        }

        #endregion

        #region IsScrubbingEnabled

        /// <inheritdoc /> 
        public override bool IsScrubbingEnabled
        {
            get
            {
                return MediaPlayer.IsScrubbingEnabled && MediaPlayer.IsScrubbingAllowed;
            }
        }

        #endregion

        /// <inheritdoc /> 
        public override bool IsMuted { get { return MediaPlayer.IsMuted; } }
        /// <inheritdoc /> 
        public override bool IsFullScreen { get { return MediaPlayer.IsFullScreen; } }
        /// <inheritdoc /> 
        public override bool IsCaptionsActive { get { return MediaPlayer.IsCaptionsActive; } }
        /// <inheritdoc /> 
        public override bool IsSlowMotion { get { return MediaPlayer.IsSlowMotion; } }
        /// <inheritdoc /> 
        public override double BufferingProgress { get { return MediaPlayer.BufferingProgress; } }
        /// <inheritdoc /> 
        public override double DownloadProgress { get { return MediaPlayer.DownloadProgress; } }
        /// <inheritdoc /> 
        public override TimeSpan StartTime { get { return GetViewModelPosition(MediaPlayer.StartTime); } }
        /// <inheritdoc /> 
        public override TimeSpan EndTime { get { return GetViewModelPosition(MediaPlayer.EndTime); } }
        /// <inheritdoc /> 
        public override TimeSpan Duration { get { return MediaPlayer.Duration; } }
        /// <inheritdoc /> 
        public override TimeSpan TimeRemaining { get { return MediaPlayer.TimeRemaining; } }
        /// <inheritdoc /> 
        public override TimeSpan Position { get { return GetViewModelPosition(MediaPlayer.Position); } }
        /// <inheritdoc /> 
        public override TimeSpan MaxPosition { get { return GetViewModelPosition(MediaPlayer.LivePosition.GetValueOrDefault(MediaPlayer.EndTime)); } }
        /// <inheritdoc /> 
        public override MediaElementState CurrentState { get { return MediaPlayer.CurrentState; } }
        /// <inheritdoc /> 
        public override double Volume { get { return MediaPlayer.Volume; } }
        /// <inheritdoc /> 
        public override IValueConverter TimeFormatConverter { get { return MediaPlayer.TimeFormatConverter; } }
        /// <inheritdoc /> 
        public override TimeSpan? SkipBackInterval { get { return MediaPlayer.SkipBackInterval; } }
        /// <inheritdoc /> 
        public override TimeSpan? SkipAheadInterval { get { return MediaPlayer.SkipAheadInterval; } }
        /// <inheritdoc /> 
        public override double SignalStrength { get { return MediaPlayer.SignalStrength; } }
        /// <inheritdoc /> 
        public override MediaQuality MediaQuality { get { return MediaPlayer.MediaQuality; } }

#if SILVERLIGHT
        /// <inheritdoc /> 
        public override bool IsDisplayModeVisible { get { return MediaPlayer.IsDisplayModeVisible; } }
#endif
        /// <inheritdoc /> 
        public override bool IsAudioSelectionVisible { get { return MediaPlayer.IsAudioSelectionVisible; } }
        /// <inheritdoc /> 
        public override bool IsCaptionsVisible { get { return MediaPlayer.IsCaptionsVisible; } }
        /// <inheritdoc /> 
        public override bool IsDurationVisible { get { return MediaPlayer.IsDurationVisible; } }
        /// <inheritdoc /> 
        public override bool IsTimeRemainingVisible { get { return MediaPlayer.IsTimeRemainingVisible; } }
        /// <inheritdoc /> 
        public override bool IsFastForwardVisible { get { return MediaPlayer.IsFastForwardVisible; } }
        /// <inheritdoc /> 
        public override bool IsFullScreenVisible { get { return MediaPlayer.IsFullScreenVisible; } }
        /// <inheritdoc /> 
        public override bool IsGoLiveVisible { get { return MediaPlayer.IsGoLiveVisible; } }
        /// <inheritdoc /> 
        public override bool IsPlayPauseVisible { get { return MediaPlayer.IsPlayPauseVisible; } }
        /// <inheritdoc /> 
        public override bool IsPositionVisible { get { return MediaPlayer.IsPositionVisible; } }
        /// <inheritdoc /> 
        public override bool IsReplayVisible { get { return MediaPlayer.IsReplayVisible; } }
        /// <inheritdoc /> 
        public override bool IsRewindVisible { get { return MediaPlayer.IsRewindVisible; } }
        /// <inheritdoc /> 
        public override bool IsSkipPreviousVisible { get { return MediaPlayer.IsSkipPreviousVisible; } }
        /// <inheritdoc /> 
        public override bool IsSkipNextVisible { get { return MediaPlayer.IsSkipNextVisible; } }
        /// <inheritdoc /> 
        public override bool IsSkipBackVisible { get { return MediaPlayer.IsSkipBackVisible; } }
        /// <inheritdoc /> 
        public override bool IsSkipAheadVisible { get { return MediaPlayer.IsSkipAheadVisible; } }
        /// <inheritdoc /> 
        public override bool IsSlowMotionVisible { get { return MediaPlayer.IsSlowMotionVisible; } }
        /// <inheritdoc /> 
        public override bool IsStopVisible { get { return MediaPlayer.IsStopVisible; } }
        /// <inheritdoc /> 
        public override bool IsTimelineVisible { get { return MediaPlayer.IsTimelineVisible; } }
        /// <inheritdoc /> 
        public override bool IsVolumeVisible { get { return MediaPlayer.IsVolumeVisible; } }
        /// <inheritdoc /> 
        public override bool IsSignalStrengthVisible { get { return MediaPlayer.IsSignalStrengthVisible; } }
        /// <inheritdoc /> 
        public override bool IsResolutionIndicatorVisible { get { return MediaPlayer.IsResolutionIndicatorVisible; } }
        
    }
}
